名字空间是开放的

  名字空间是开放的;也就是说,你可以通过多个名字空间声明给它加入名字。例如,

    namespace A {
        int f();            // 现在A有成员f()
    }

    namespace A {
        int g();            // 现在A有成员f()和g()
    }

通过这种方式,我们就能支持将一个名字空间中放入几个大的程序片段,其方式就像老的库和应用存在于同一个全局名字空间中那样。为做到这些,我们必须允许一个名字空间的定义分布到多个头文件和源代码文件里。正如前面计算器的例子(8.2.4节)所示,名字空间的开放性使我们可以通过展示名字空间不同部分的方式,为不同种类的用户提供不同的界面。这种开发性对于转变也很有帮助。例如,

    // 我的头文件
        void f();            // 我的函数
        // ...
        #include <stdio.h>
        int g();             // 我的函数
        // ...

可以重写,且不必重排声明的顺序:

    namespace Mine {
        void f();            // 我的函数
        // ...
    }

    #include <stdio.h>

    namespace Mine {
        int g();             // 我的函数
        // ...
    }

在写新代码时,我倾向于使用较小的名字空间(8.2.8节),而不是将代码的主要片段都塞进同一个名字空间里。然而,在将一个软件的主要片段转为采用名字空间时,这种做法通常就不实际了。

  在定义一个名字空间里已经声明过的成员时,更安全的方式是采用Mine::语法形式,而不是重新打开Mine。例如,

    void Mine::ff()            // 错误❌:在Mine里没有声明ff()
    {
        // ...
    }

编译器能够捕捉到这个错误。然而,由于在一个名字空间里可以定义新函数,编译器就无法捕捉在重新打开的名字空间里出现的同样的错误

    namespace Mine {            // 重新打开Mine以定义函数
        void ff()            // 呜呼!在Mine里没有声明ff(),这个定义将ff()加进了Mine
        {
            // ...
        }
        // ...
    }

编译器没办法知道你并不想要这个新的ff()。

  名字空间别名(8.2.7节)也可以在定义中用做名字的限定词。但是却不能通过名字空间的别名去重新打开那个名字空间。

🔚